package io.kiki.sba.registry.server.clientInterface.providedata;

import io.kiki.sba.registry.common.model.console.CircuitBreakerData;
import io.kiki.sba.registry.common.model.console.PersistenceData;
import io.kiki.sba.registry.common.model.constants.ValueConstants;
import io.kiki.sba.registry.server.clientInterface.bootstrap.Config;
import io.kiki.sba.registry.server.clientInterface.providedata.FetchCircuitBreakerService.CircuitBreakerStorage;
import io.kiki.sba.registry.server.shared.providedata.AbstractFetchPersistenceSystemProperty;
import io.kiki.sba.registry.server.shared.providedata.SystemDataStorage;
import io.kiki.sba.registry.store.api.meta.ProvideDataRepository;
import io.kiki.sba.registry.util.JsonUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Collections;
import java.util.Set;


public class FetchCircuitBreakerService extends AbstractFetchPersistenceSystemProperty<CircuitBreakerStorage, CircuitBreakerStorage> {

    private static final Logger logger = LoggerFactory.getLogger(FetchCircuitBreakerService.class);
    private static final CircuitBreakerStorage INIT = new CircuitBreakerStorage(INIT_VERSION, false, Collections.emptySet(), Collections.emptySet());
    @Autowired
    private Config config;
    @Autowired
    private ProvideDataRepository provideDataRepository;

    public FetchCircuitBreakerService() {
        super(ValueConstants.CIRCUIT_BREAKER_DATA_ID, INIT);
    }

    @Override
    protected int getSystemPropertyIntervalMillis() {
        return config.getSystemPropertyIntervalMillis();
    }

    @Override
    protected CircuitBreakerStorage fetchFromPersistence() {
        PersistenceData persistenceData = provideDataRepository.get(ValueConstants.CIRCUIT_BREAKER_DATA_ID);
        if (persistenceData == null) {
            return INIT;
        }
        CircuitBreakerData read = JsonUtils.read(persistenceData.getData(), CircuitBreakerData.class);
        return new CircuitBreakerStorage(persistenceData.getVersion(), read.addressSwitch(INIT.addressSwitch), read.getAddress(), read.getOverflowAddress());
    }

    @Override
    protected boolean doProcess(CircuitBreakerStorage expect, CircuitBreakerStorage update) {

        try {
            if (!compareAndSet(expect, update)) {
                logger.error("update circuit breaker address:{} fail.", update);
                return false;
            }
            logger.info("Fetch circuit breaker data, prev={}, current={}", expect, update);
        } catch (Throwable t) {
            logger.error("update circuit breaker address:{} error.", update, t);
        }
        return true;
    }

    public Set<String> getStopPushCircuitBreaker() {
        return this.storage.get().address;
    }

    public Set<String> getOverflowAddress() {
        return this.storage.get().overflowAddress;
    }

    public boolean isSwitchOpen() {
        return this.storage.get().addressSwitch;
    }

    public static class CircuitBreakerStorage extends SystemDataStorage {

        final boolean addressSwitch;
        final Set<String> address;
        final Set<String> overflowAddress;

        public CircuitBreakerStorage(long version, boolean addressSwitch, Set<String> address, Set<String> overflowAddress) {
            super(version);
            this.addressSwitch = addressSwitch;
            this.address = address;
            this.overflowAddress = overflowAddress;
        }


    }
}
